from traceback import format_exception
import sys

from yaaps.request import WSGIRequest
from yaaps.urls import dispatch
from yaaps.response import WSGIResponse
import settings

middleware_instances = [m() for m in settings.MIDDLEWARE]

def _exception_to_string():
    str_list = format_exception(sys.exc_info()[0],
                                sys.exc_info()[1],
                                sys.exc_info()[2])
    if len(str_list) > 1:
        return '%s%s\n\n%s' % (str_list[-1], str_list[-2], ''.join(str_list))
    else:
        return ''.join(str_list)

class YaapsApp(object):
    def __init__(self, env, start_response):
        if not env['PATH_INFO'].endswith("/"):
            env['PATH_INFO'] = env['PATH_INFO'] + "/" 
        self.request = request = WSGIRequest(env, start_response)
        request.logger = env['wsgi.errors']
        response = None
        is_exception = False
        for middleware in middleware_instances:
            try:
                if hasattr(middleware, "do_request"):
                    response = middleware.do_request(request)
                    if response is not None:
                        break
            except Exception as e:
                is_exception = True
        if response is None and is_exception == False:
            try:
                response = dispatch(request)
            except Exception as e:
                is_exception = True
        if is_exception == False:
            for middleware in reversed(middleware_instances):
                try:
                    if hasattr(middleware, "do_response"):
                        middleware_response = middleware.do_response(request, response)
                        if middleware_response is not None:
                            response = middleware_response
                except:
                    is_exception = True
        if is_exception:
            for middleware in reversed(middleware_instances):
                try:
                    if hasattr(middleware, "do_exception"):
                        middleware_response = middleware.do_exception(request, response)
                        if middleware_response is not None:
                            response = middleware_response
                except Exception as e:
                    pass
            if response is None:
                if settings.DEBUG:
                    body = _exception_to_string()
                else:
                    body = ''
                response = WSGIResponse(headers = {}, content = body, http_status = "500 INTERNAL ERROR")
        self.response = response
        
    def __iter__(self):
        yield self.response.send(self.request.start_response)
